using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Media.Effects;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using WGMClient.Core;
using WGMClient.HelperClasses;
using System.Windows.Media.Animation;
using WGMClient.Controls;
using WGMClient.Properties;
using System.Windows.Threading;
using WGMClient.WGMSvc;
using System.Net;
using System.IO;
using System.Xml.Serialization;
using System.Reflection;

namespace WGMClient
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class MainClientWindow : Window, IMessageListener
    {
        #region Interop Helpers
        [DllImport("user32.dll")]
        private static extern int FlashWindowEx(ref FLASHWINFO pwfi);

        // Unmanaged function from user32.dll
        [DllImport("user32.dll")]
        static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        // Struct we'll need to pass to the function
        internal struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        private struct FLASHWINFO
        {
            public Int32 cbSize;
            public IntPtr hwnd;
            public Int32 dwFlags;
            public Int32 uCount;
            public Int32 dwTimeout;
        }
        #endregion
        Color _normalTitleBarColour = Color.FromArgb(128, 102, 102, 108);
        private bool _titleBarFlashing = false;
        private bool _iconFlashing = false;
        private bool _clientListInitComplete = false;
        private DispatcherTimer _retrieveTimer = new DispatcherTimer();
        private DispatcherTimer _refreshTimer = new DispatcherTimer();
        private DispatcherTimer _updateTimer = new DispatcherTimer();
        private DispatcherTimer _statusTimer = new DispatcherTimer();
        NotifyIcon _notifyIcon = new NotifyIcon();
        ClientEngine _engine = new ClientEngine();
        private int _currentVersion = 0;
        public IntPtr WindowHandle { get { return new WindowInteropHelper(this).Handle; } }
        public MainClientWindow()
        {
            Registry.WorkingDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\wgm\\";
            Registry.SettingsFile = Registry.WorkingDir + "wgm_settings.xml";
            HelperClasses.HelperFunctions.LoadSettings();
            InitializeComponent();

            GetCurrentVersion();
            this.Top = Math.Max(10, HelperClasses.Registry.Settings.LastWindowY);
            this.Left =Math.Max(10, HelperClasses.Registry.Settings.LastWindowX);
            this.Topmost = HelperClasses.Registry.Settings.AlwaysOnTop;
            SetupTrayIcon();
            HelperClasses.Registry.MainWindow = this;
            HelperClasses.Registry.RegisterListener(this);
            _conversationSelector.AssociatedTab = _conversationsTab;
            _profileSelector.AssociatedTab = _profileTab;
            _settingsSelector.AssociatedTab = _settingsTab;
            _historySelector.AssociatedTab = _historyTab;
            _retrieveTimer.Interval = TimeSpan.FromSeconds(HelperClasses.Registry.Settings.RetrieveTimerInterval);
            _retrieveTimer.Tick += new EventHandler(OnRetrieveTimerTick);
            _refreshTimer.Interval = TimeSpan.FromMinutes(HelperClasses.Registry.Settings.RefreshtimerInterval);
            _refreshTimer.Tick += new EventHandler(OnRefreshTimerTick);
            _updateTimer.Interval = TimeSpan.FromMinutes(5);
            _updateTimer.Tick += new EventHandler(_updateTimer_Tick);
            _updateTimer.Start();
            _statusTimer.Interval = TimeSpan.FromSeconds(30);
            _statusTimer.Tick += new EventHandler(_statusTimer_Tick);
            Registry.MacAddress = HelperFunctions.GetMacAddress();
            Microsoft.Win32.SystemEvents.PowerModeChanged += new Microsoft.Win32.PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
        }



        void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
        {
            this.InvalidateVisual();
            this.UpdateLayout();
        }

        void _updateTimer_Tick(object sender, EventArgs e)
        {
            _updateTimer.Stop();
            ThreadPool.QueueUserWorkItem
            (
                delegate
                {
                    try
                    {
                        
                        WebClient client = new WebClient();
                        client.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
                        client.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
                        string baseUrl = "http://www.hartlabs.com/downloads/wgm/repo/";
                        string retVal = client.DownloadString(baseUrl + "/manifest.txt");

                        Thread.Sleep(100);
                        var items = retVal.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                        string version = items[0];
                        int ver = Convert.ToInt32(version.Replace(".", ""));
                        if (ver > _currentVersion)
                        {
                            SetClickableNotification("A new update is available, click here to update.", Colors.White, Colors.Purple, "_update_","_update_");
                            _updateTimer.Stop();
                        }
                    }
                    catch (Exception ex)
                    {
                        HelperClasses.HelperFunctions.LogException(ex);
                    }
                    _updateTimer.Start();
                }
            );
        }
        private void GetCurrentVersion()
        {
            try
            {
                var currDir = System.Windows.Forms.Application.StartupPath;
                var currDirName= new DirectoryInfo(currDir).Name;
                try
                {
                    _currentVersion = Convert.ToInt32(currDirName.Replace(".", ""));
                    Registry.CurrentVersion = currDirName;
                }
                catch
                {
                    SetDropDownMessage("This is an unkown version", "_version_");
                    Registry.CurrentVersion = "unknown";
                }

            }
            catch (Exception ex) { HelperClasses.HelperFunctions.LogException(ex); }
        }
        void OnRefreshTimerTick(object sender, EventArgs e)
        {
            _refreshTimer.Stop();
            HelperClasses.Registry.Engine.SendMessageToServer(new WGMClient.WGMSvc.WGMMessage() { MessageType = WGMClient.WGMSvc.MessageTypes.USER_REQUEST_PROFILES, SenderLogon = HelperClasses.Registry.Username, ReceiverLogon = "", SenderTimeStamp = DateTime.Now });
        }
        void _statusTimer_Tick(object sender, EventArgs e)
        {
            _statusTimer.Stop();
            // Get the system uptime
            int systemUptime = Environment.TickCount;
            // The tick at which the last input was recorded
            int lastInputTicks = 0;
            // The number of ticks that passed since last input
            int idleTicks = 0;

            int idleSeconds = 0;
            // Set the struct
            LASTINPUTINFO LastInputInfo = new LASTINPUTINFO();
            LastInputInfo.cbSize = (uint)Marshal.SizeOf(LastInputInfo);
            LastInputInfo.dwTime = 0;
            // If we have a value from the function
            if (GetLastInputInfo(ref LastInputInfo))
            {
                // Get the number of ticks at the point when the last activity was seen
                lastInputTicks = (int)LastInputInfo.dwTime;
                // Number of idle ticks = system uptime ticks - number of ticks at last input
                idleTicks = systemUptime - lastInputTicks;

                idleSeconds = idleTicks / 1000;

                if (idleSeconds > 60 * 5)
                {
                    Registry.Engine.SendMessageToServer(new WGMMessage() { MessageType = MessageTypes.USER_STATE_AWAY, SenderLogon = Registry.Username });
                    Registry.MyState = ClientState.AWAY;
                }
                else
                {
                    Registry.Engine.SendMessageToServer(new WGMMessage() { MessageType = MessageTypes.USER_STATE_NORMAL, SenderLogon = Registry.Username });
                    Registry.MyState = ClientState.ONLINE;
                }
            }
            _statusTimer.Start();
        }
        void OnRetrieveTimerTick(object sender, EventArgs e)
        {
            HelperClasses.Registry.Engine.SendMessageToServer(new WGMClient.WGMSvc.WGMMessage() { MessageType = WGMClient.WGMSvc.MessageTypes.USER_REQUEST_DBMESSAGES, SenderLogon = HelperClasses.Registry.Username, ReceiverLogon="", SenderTimeStamp = DateTime.Now });
            
        }
        #region NotifyEvents
        public void NotifyServerMessage(WGMSvc.WGMMessage message)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        try
                        {
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.USER_LOGON_SUCCESS)
                            {
                                HelperClasses.HelperFunctions.SlideOut(_loginView, _loginView.ActualWidth * -1, 0, TimeSpan.FromSeconds(0.2));
                                HelperClasses.HelperFunctions.SlideOut(_wgmBgImg, 0, _wgmBgImg.ActualHeight + 10, TimeSpan.FromSeconds(0.2));
                                this.ResizeMode = ResizeMode.CanResizeWithGrip;
                                _mainTab.IsSelected = true;
                                var data = message.Message as List<object>;
                                var profileList = data[0] as List<WGMSvc.WGMMember>;
                                var onlineList = data[1] as List<string>;
                                foreach (var client in profileList)
                                {
                                    if (client.Username.ToLower().Trim() == HelperClasses.Registry.Username.ToLower().Trim())
                                    {
                                        HelperClasses.Registry.MyInfo = new WGMLocalClient();
                                        HelperClasses.Registry.MyInfo.MemberObject = client;
                                        _myInfo.Text = HelperClasses.Registry.MyInfo.DisplayName;
                                        _myInfo.SubText = HelperClasses.Registry.MyInfo.DisplayStatus;
                                        Registry.NotifyListeners(new LocalMessage() { MessageType = LocalMessageTypes.MY_INFO_CHANGED });
                                    }
                                }
                                _sizeControls.Visibility = Visibility.Visible;
                                AddMainConversationTab();
                                RefreshClientList(message.Message as List<object>);
                                HelperClasses.Registry.Engine.SendMessageToServer(new WGMClient.WGMSvc.WGMMessage() { MessageType = WGMClient.WGMSvc.MessageTypes.USER_REQUEST_DBMESSAGES, SenderLogon = HelperClasses.Registry.Username, ReceiverLogon = "", SenderTimeStamp = DateTime.Now });


                                HelperClasses.Registry.Engine.SendMessageToServer(new WGMClient.WGMSvc.WGMMessage() { MessageType = WGMClient.WGMSvc.MessageTypes.USER_REQUEST_PROFILE_IMAGE, SenderLogon = HelperClasses.Registry.Username, ReceiverLogon = HelperClasses.Registry.Username, SenderTimeStamp = DateTime.Now });
                                HelperClasses.HelperFunctions.SizeTo(this, Math.Max( HelperClasses.Registry.Settings.LastWindowWidth,800), Math.Max( HelperClasses.Registry.Settings.LastWindowHeight,600), TimeSpan.FromSeconds(0.2));
                                _retrieveTimer.Start();
                                _refreshTimer.Start();
                                _statusTimer.Start();
                                _notifyIcon.Text = "WGM Beta3 - (" + HelperClasses.Registry.Username + ")";
                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.SERVER_PROFILES_RESPONSE)
                            {
                                RefreshClientList(message.Message as List<object>);
                                _refreshTimer.Start();
                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.SERVER_PROFILE_IMAGE_RESPONSE)
                            {
                                if (message.ReceiverLogon.ToLower().Trim() == HelperClasses.Registry.Username.ToLower().Trim())
                                {
                                    HelperClasses.Registry.MyInfo.ImageData = message.Message as byte[];

                                    Registry.NotifyListeners(new LocalMessage() { MessageType = LocalMessageTypes.MY_IMAGE_CHANGED });
                                }

                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.SERVER_NEW_USER_CREATED)
                            {
                                AddCLItem(message.Message as WGMSvc.WGMMember, false, false);
                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.USER_CHANGED_IMAGE)
                            {
                                HelperClasses.Registry.Engine.SendMessageToServer(new WGMClient.WGMSvc.WGMMessage() { MessageType = WGMClient.WGMSvc.MessageTypes.USER_REQUEST_PROFILE_IMAGE, SenderLogon = HelperClasses.Registry.Username, ReceiverLogon = message.SenderLogon, SenderTimeStamp = DateTime.Now });

                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.SERVER_PROFILE_RESPONSE)
                            {
                                if (message.SenderLogon.ToLower().Trim() == HelperClasses.Registry.Username.ToLower().Trim())
                                {
                                    HelperClasses.Registry.MyInfo.MemberObject = message.Message as WGMSvc.WGMMember;

                                    Registry.NotifyListeners(new LocalMessage() { MessageType = LocalMessageTypes.MY_INFO_CHANGED });
                                }
                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.USER_CHANGED_PROFILE)
                            {
                                HelperClasses.Registry.Engine.SendMessageToServer(new WGMClient.WGMSvc.WGMMessage() { MessageType = WGMClient.WGMSvc.MessageTypes.USER_REQUEST_PROFILE, SenderLogon = HelperClasses.Registry.Username, ReceiverLogon = message.SenderLogon, SenderTimeStamp = DateTime.Now });
                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.GLOBAL_MESSAGE || message.MessageType == WGMClient.WGMSvc.MessageTypes.PRIVATE_MESSAGE || message.MessageType == MessageTypes.GLOBAL_FILE_XFER || message.MessageType == MessageTypes.PRIVATE_FILE_XFER)
                            {
                                if (HelperClasses.HelperFunctions.GetForegroundWindow() != new WindowInteropHelper(this).Handle)
                                {
                                    FlashWindow();
                                }
                                
                                if (!this.IsVisible)
                                {
                                    FlashTrayIcon(500);
                                }

                            }
                            if (message.MessageType == WGMClient.WGMSvc.MessageTypes.SERVER_DBMESSAGES_REPONSE)
                            {
                                var messages = message.Message as List<WGMSvc.WGMMessage>;
                                foreach (var item in messages)
                                {
                                    if (item != null)
                                        HelperClasses.Registry.NotifyListeners(item);
                                    else
                                    {
                                        HelperClasses.Registry.MainWindow.SetDropDownMessage("Packet Loss Detected!", Colors.White, Colors.OrangeRed, 3500);
                                    }

                                }

                                _retrieveTimer.Start();
                            }
                            if (message.MessageType == MessageTypes.USER_STATE_AWAY && message.SenderLogon.ToLower().Trim() != Registry.Username.ToLower().Trim())
                            {
                                var cli = GetCLItem(message.SenderLogon);
                                if (cli != null)
                                    SetClientOnline(cli, true, ClientState.AWAY);
                            }
                            if (message.MessageType == MessageTypes.USER_STATE_BUSY && message.SenderLogon.ToLower().Trim() != Registry.Username.ToLower().Trim())
                            {
                                var cli = GetCLItem(message.SenderLogon);
                                if (cli != null)
                                    SetClientOnline(cli, true, ClientState.BUSY);
                            }
                            if (message.MessageType == MessageTypes.USER_STATE_NORMAL && message.SenderLogon.ToLower().Trim() != Registry.Username.ToLower().Trim())
                            {
                                var cli = GetCLItem(message.SenderLogon);
                                if (cli != null)
                                    SetClientOnline(cli, true, ClientState.ONLINE);
                            }
                            if (message.MessageType == MessageTypes.SERVER_SHUTDOWN_USER)
                            {
                                HelperFunctions.SaveSettings();
                                Registry.Engine.SendMessageToServer(new WGMMessage() { MessageType = MessageTypes.USER_LEAVING, SenderLogon = Registry.Username });
                                ShutdownApplication();
                            }
                            if (message.MessageType == MessageTypes.SERVER_RESTART_USER)
                            {
                                GetLauncherAndDeploy();
                            }
                        }
                        catch (Exception ex)
                        {
                            HelperClasses.HelperFunctions.LogException(ex);
                        }

                    }
                )
            );
        }


        public void NotifyLocalMessage(LocalMessage message)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        try
                        {
                            if (message.MessageType == LocalMessageTypes.MY_IMAGE_CHANGED)
                            {
                                _myInfo.SetBackgroundImage(HelperClasses.Registry.MyInfo.ImageData);
                                _myInfo.HasImage = HelperClasses.Registry.Settings.ShowContactImages;
                            }
                            if (message.MessageType == LocalMessageTypes.MY_INFO_CHANGED)
                            {
                                SetMyInfoBox();
                            }
                            if (message.MessageType == LocalMessageTypes.CONNECTION_RESTORED)
                            {
                                _retrieveTimer.Start();
                                _refreshTimer.Start();
                            }
                            if (message.MessageType == LocalMessageTypes.CONNECTION_FAULTED)
                            {
                                _retrieveTimer.Start();
                            }
                            if (message.MessageType == LocalMessageTypes.SYSTEM_OPTIONS_CHANGED)
                            {
                                _myInfo.HasImage = HelperClasses.Registry.Settings.ShowContactImages;
                                this.Topmost = HelperClasses.Registry.Settings.AlwaysOnTop;
                                SetPopupMenu();
                            }
                        }
                        catch (Exception ex)
                        {
                            HelperFunctions.LogException(ex);
                        }
                    }
                )
            );
        }
        private void SetMyInfoBox()
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        _myInfo.Text = HelperClasses.Registry.MyInfo.DisplayName;
                        _myInfo.SubText = HelperClasses.Registry.MyInfo.DisplayStatus;
                    }
                )
            );

        }

        private void RefreshClientList(List<object> data)
        {
            var profileList = data[0] as List<WGMSvc.WGMMember> ;
            var onlineList = data[1] as List<string>;
            foreach (var client in profileList)
            {
                if (client.Username.ToLower().Trim() == HelperClasses.Registry.Username.ToLower().Trim())
                {
                    HelperClasses.Registry.MyInfo.MemberObject = client;
                    _myInfo.Text = HelperClasses.Registry.MyInfo.DisplayName;
                    _myInfo.SubText = HelperClasses.Registry.MyInfo.DisplayStatus;
                }
                else if (GetCLItem(client.Username) == null)                {
                    
                    AddCLItem(client, false, onlineList.Contains(client.Username.ToLower().Trim(),StringComparer.CurrentCultureIgnoreCase));
                }
                else
                {
                    UpdateCLItem(GetCLItem(client.Username), client, onlineList.Contains(client.Username.ToLower().Trim(), StringComparer.CurrentCultureIgnoreCase), GetCLItem(client.Username).AssociatedClient.OnlineState);
                }
            }            
        }



        private void AddMainConversationTab()
        {
            if (_clientListInitComplete)
            {
                return;
            }
            WGMSvc.WGMMember member = new WGMClient.WGMSvc.WGMMember();
            member.DisplayName = "Main Conversation";
            member.DisplayStatus = "Group Messages";
            member.Username = "SERVER";
            member.FontColourR = 255;
            member.FontFace = "Verdana";
            member.FontSize = 12;
            member.IsFontBold = false;
            member.IsFontItalics = false;
            member.IsFontUnderlined = false;
            
            AddCLItem(member, true, true);
            _clientListInitComplete = true;
        }
        public BackgroundTextBlock GetCLItem(string username)
        {
            for (int count = 0; count < _contactListPanel.Children.Count; count++)
            {
                if (_contactListPanel.Children[count] is BackgroundTextBlock)
                {
                    BackgroundTextBlock curr = _contactListPanel.Children[count] as BackgroundTextBlock;
                    if (curr.AssociatedClient.Username.ToLower().Trim() == username.ToLower().Trim())
                        return curr;
                }
            }
            return null;
        }
        private void AddCLItem(WGMSvc.WGMMember clientInfo, bool isMainWindow, bool isOnline)
        {
            WGMLocalClient client = new WGMLocalClient();
            client.IsOnline = isOnline;
            if (isMainWindow)
            {
                client.IsMainWindow = true;
                client.MemberObject = clientInfo;
                System.Drawing.Image img = System.Drawing.Image.FromFile(System.Windows.Forms.Application.StartupPath + "\\Images\\group.png");
                client.ImageData = HelperClasses.HelperFunctions.ImageToByteArray(img, img.RawFormat);
            }
            client.MemberObject = clientInfo;
            if (!isMainWindow && client.Username.ToLower().Trim() == Registry.Username.ToLower().Trim())
                return;
            BackgroundTextBlock cli = new BackgroundTextBlock();
            cli.MaxTextWidth = 200;
            cli.UnderlineWidth = 200;
            cli.UnderlineAlignment = System.Windows.HorizontalAlignment.Left;
            cli.Margin = new Thickness(0, 2, 0, 2);
            cli.OuterBorderRadius = new CornerRadius(5, 0, 0, 5);
            cli.OuterBorderBackGround = new SolidColorBrush(Colors.Transparent);
            cli.BorderRadius = new CornerRadius(5, 0, 0, 5);
            cli.BorderBackground = new SolidColorBrush(Colors.Transparent);
            cli.InnerBorderMargin = new Thickness(1);
            cli.ImageOnLeft = true;
            cli.FontSize = 12;
            cli.Text = client.DisplayName;
            cli.SubText = client.DisplayStatus;
            cli.SubLabelFontSize = 9;
            cli.SubLabelFontWeight = FontWeights.Normal;
            cli.SubLabelFontStyle = FontStyles.Italic;
            cli.SubTextMargin = new Thickness(8, 0, 0, 0);
            cli.HasImage = true;
            cli.ImageOnLeft = true;
            cli.ImageHeight = 15;
            cli.ImageWidth = 15;


            try
            {
                cli.ImageStretch = Stretch.Fill;
            }
            catch { }
            cli.FontWeight = FontWeights.Bold;

            TabItem ti = new TabItem();
            ti.Visibility = Visibility.Collapsed;
            cli.AssociatedTab = ti;
            InternalChatControl icc = new InternalChatControl();
            icc.IsMainWindow = client.IsMainWindow;
            icc.AssociatedSelector = cli;
            icc.AssociatedTab = ti;
            

            icc.AssociatedClient = client;
            Registry.Settings.AddToSoundList(client.Username, false);
            icc.SetImage(client.ImageData);
            icc.PlaySound = Registry.Settings.HasSound(client.Username);
            ti.Content = icc;

            cli.UnderlineColour = new SolidColorBrush(Colors.OrangeRed); ;
            cli.MouseLeftButtonDown += new MouseButtonEventHandler(OnContactSelected);
            cli.IsSelected = icc.IsMainWindow;
            cli.Cursor = System.Windows.Input.Cursors.Hand;
            cli.AssociatedClient = client;
            cli.ID = client.Username;

            client.AssociatedChatControl = icc;
            client.AssociatedSelector = cli;
            client.AssociatedTab = ti;
            _chatTabControl.Items.Add(ti);
            SetClientOnline(cli, client.IsOnline || client.IsMainWindow, ClientState.ONLINE);
            if (!client.IsMainWindow)
            {
                cli.SetTextTooltip(client.DisplayString);
                for (int count = 1; count < _contactListPanel.Children.Count; count++)
                {
                    if (_contactListPanel.Children[count] is BackgroundTextBlock)
                    {
                        BackgroundTextBlock curr = _contactListPanel.Children[count] as BackgroundTextBlock;
                        if (String.Compare(cli.AssociatedClient.DisplayName.Trim(), curr.AssociatedClient.DisplayName.Trim(), true) < 0)
                        {
                            _contactListPanel.Children.Insert(count, cli);
                            return;
                        }
                    }
                }                
                _contactListPanel.Children.Add(cli);
            }
            else
            {
                cli.SetTextTooltip("Group Conversation");
                _contactListPanel.Children.Insert(0, cli);
            }
        }
        public void SetClientOnline(BackgroundTextBlock cli, bool isOnline, ClientState state)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        bool wasOnline = cli.AssociatedClient.IsOnline;
                        cli.AssociatedClient.IsOnline = isOnline;
                        if (isOnline)
                        {
                            switch (state)
                            {
                                case ClientState.ONLINE:
                                    {
                                        cli.BackgroundImage = new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\Images\\online.png"));
                                        cli.SetImageTooltip("Online");
                                        break;
                                    }
                                case ClientState.AWAY:
                                    {
                                        cli.BackgroundImage = new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\Images\\away.png"));
                                        cli.SetImageTooltip("Idle");
                                        break;
                                    }

                            }
                            cli.ImageGlowColor = cli.AssociatedClient.IsMainWindow ? Colors.LimeGreen : cli.AssociatedClient.UserColor;
                            cli.ImageGlowRadius = 5;
                            cli.GlowImage = true;

                            if (HelperClasses.Registry.MainWindow.IsVisible == false && HelperClasses.Registry.Settings.ShowOnlinePopup && wasOnline!= cli.AssociatedClient.IsOnline)
                            {
                                PopupWindow popup = new PopupWindow();
                                popup.ShowWindow(10, "Contact Joining", cli.AssociatedClient.DisplayName + " is now online.", cli.AssociatedClient);
                            }
                        }
                        else
                        {
                            cli.SetImageTooltip("Offline\nMessages will be delivered to " + cli.AssociatedClient.DisplayName + " when the contact is next online");
                            cli.BackgroundImage = new BitmapImage(new Uri(System.Windows.Forms.Application.StartupPath + "\\Images\\offline.png"));
                            cli.BlurImage = true;

                            if (HelperClasses.Registry.MainWindow.IsVisible == false && HelperClasses.Registry.Settings.ShowOfflinePopup && wasOnline!= cli.AssociatedClient.IsOnline)
                            {
                                PopupWindow popup = new PopupWindow();
                                popup.ShowWindow(10, "Contact Leaving", cli.AssociatedClient.DisplayName + " is leaving.", cli.AssociatedClient);
                            }
                        }
                    }
                )
            );
        }
        public void UpdateContactSelector(WGMSvc.WGMMember memberInfo)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        BackgroundTextBlock cli = null;
                        cli = GetCLItem(memberInfo.Username);
                        if (cli != null)
                        {
                            UpdateCLItem(cli, memberInfo, cli.AssociatedClient.IsOnline, cli.AssociatedClient.OnlineState);
                        }
                    }
                )
            );
        }
        public void UpdateCLItem(BackgroundTextBlock cli, WGMSvc.WGMMember clientInfo, bool isOnline, ClientState state)
        {
            _contactListPanel.Children.Remove(cli as UIElement);
            cli.AssociatedClient.MemberObject = clientInfo;
            cli.Text = cli.AssociatedClient.DisplayName;
            cli.SubText = cli.AssociatedClient.DisplayStatus;
            
            SetClientOnline(cli, isOnline, state);
            for (int count = 1; count < _contactListPanel.Children.Count; count++)
            {
                if ((_contactListPanel.Children[count] is BackgroundTextBlock))
                {
                    var curr = (_contactListPanel.Children[count] as BackgroundTextBlock);
                    if (String.Compare(cli.AssociatedClient.DisplayName.Trim().ToLower(), curr.AssociatedClient.DisplayName.Trim().ToLower()) < 0)
                    {
                        _contactListPanel.Children.Insert(count, cli);
                        return;
                    }
                }
            }
            _contactListPanel.Children.Add(cli);

        }




        void OnContactSelected(object sender, MouseButtonEventArgs e)
        {

            (sender as BackgroundTextBlock).IsSelected = true;

            
        }
        #endregion
        #region WindowBehaviour
        private void OnTitleBarMouseDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        private void OnMinimize(object sender, MouseButtonEventArgs e)
        {
            this.WindowState = WindowState.Minimized;            
        }

        private void OnMaxRestore(object sender, MouseButtonEventArgs e)
        {
            if (this.WindowState == WindowState.Normal)
                this.WindowState = WindowState.Maximized;
            else
                this.WindowState = WindowState.Normal;
        }

        private void OnClose(object sender, MouseButtonEventArgs e)
        {
            this.Close();
        }
        private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (HasActiveNotification())
                FlashTrayIcon(500);
            this.Visibility = Visibility.Collapsed;
            this.WindowState = WindowState.Minimized;
            e.Cancel = true;
        }
        public void ShowMainWindow()
        {
            this.Visibility = Visibility.Visible;
            this.WindowState = WindowState.Minimized;


            SetForegroundWindow(new WindowInteropHelper(System.Windows.Application.Current.MainWindow).Handle);
            _iconFlashing = false;
        }
        #endregion
        #region UICalls
        public void FlashTitleBar(Color colour1, Color colour2, int flashCount, int flashPeriod, bool restoreOriginalColour)
        {
            ThreadPool.QueueUserWorkItem
            (
                delegate
                {
                    if (_titleBarFlashing)
                        return;
                    _titleBarFlashing = true;
                    
                    if (flashCount < 0)
                    {
                        while (_titleBarFlashing)
                        {
                            SetTitleBarColour(colour1, colour2);
                            Thread.Sleep(flashPeriod);
                            SetTitleBarColour(_normalTitleBarColour, _normalTitleBarColour);
                            Thread.Sleep(flashPeriod);
                        }
                        SetTitleBarColour(_normalTitleBarColour, _normalTitleBarColour);
                        return;
                    }
                    for (int count = 0; count < flashCount * 2; count++)
                    {
                        if (!_titleBarFlashing)
                        {
                            break;
                        }
                        if (count % 2 == 0)
                        {
                            SetTitleBarColour(colour1, colour2);
                        }
                        else
                        {
                            SetTitleBarColour(_normalTitleBarColour, _normalTitleBarColour);
                        }
                        Thread.Sleep(flashPeriod);
                    }
                    if (restoreOriginalColour)
                        SetTitleBarColour(_normalTitleBarColour, _normalTitleBarColour);
                    else
                        SetTitleBarColour(colour1, colour2);

                    _titleBarFlashing = false;
                }
            );
        }
        public void ClearIconFlashing()
        {
            _iconFlashing = false;
        }
        public void ClearTitleBarColour()
        {
            _titleBarFlashing = false;
            SetTitleBarColour(_normalTitleBarColour, _normalTitleBarColour);
        }
        public void SetTitleBarColour(Color colour1, Color colour2)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        _titleBorder.Background = new LinearGradientBrush(colour1, colour2, 0);
                        
                    }
                )
            );
        }
        public void SetTitleBarColour(Color colour)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        _titleBorder.Background = new LinearGradientBrush(_normalTitleBarColour, colour, new Point(0.5,0.5),new Point(1,0.5));

                    }
                )
            );
        }
        public void SetTitleBarMessage(string text, Color colour)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        _titleMessageTB.Text = text;
                        _titleMessageTB.LabelForeground = new SolidColorBrush(colour);
                        
                    }
                )
            );
        }
        public void SetTitleBarMessage(string text)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        _titleMessageTB.Text = text;
                        _titleMessageTB.LabelForeground = new SolidColorBrush(Colors.White);
                    }
                )
            );
        }
        public void SetTitle(string text)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {

                        _titleTB.Text = text;
                    }
                )
            );
        }
        public void FlashTrayIcon(int flashPeriod)
        {
            ThreadPool.QueueUserWorkItem
            (
                delegate
                {
                    if (_iconFlashing)
                        return;
                    _iconFlashing = true;
                    while (_iconFlashing)
                    {
                        _notifyIcon.Icon = new System.Drawing.Icon(System.Windows.Forms.Application.StartupPath + "\\Images\\app_icon_new_message.ico");
                        Thread.Sleep(flashPeriod);
                        _notifyIcon.Icon = new System.Drawing.Icon(System.Windows.Forms.Application.StartupPath + "\\Images\\app_normal.ico");
                        Thread.Sleep(flashPeriod);
                    }
                    _notifyIcon.Icon = new System.Drawing.Icon(System.Windows.Forms.Application.StartupPath + "\\Images\\app_normal.ico");
                }
            );
        }
        public void SetDropDownMessage(string text, Color fontColor, Color backgroundColor, int timeout)
        {
            ThreadPool.QueueUserWorkItem
            (
                delegate
                {
                    string id = DateTime.Now.ToString()+ DateTime.Now.Ticks.ToString();
                    SetDropDownMessage(text, fontColor, backgroundColor, id);
                    Thread.Sleep(timeout);
                    ClearDropDownMessage(id);
                }
            );
        }
        public void SetDropDownMessage(string text, Color fontColor, Color backgroundColor, string id)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        ClearDropDownMessage(id);
                        BackgroundTextBlock btb = new BackgroundTextBlock();
                        btb.ID = id;
                        btb.Effect = new DropShadowEffect();
                        btb.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                        btb.VerticalAlignment = VerticalAlignment.Top;
                        btb.FontFamily = new FontFamily("Verdana");
                        btb.BorderRadius= new CornerRadius(0,0,20,0);
                        btb.TextMargin= new Thickness(20,5,20,5);
                        btb.LabelFontSize=12;
                        btb.Text = text;
                        btb.LabelForeground = new SolidColorBrush(fontColor);
                        btb.BorderBackground = new SolidColorBrush(backgroundColor);
                        
                        _mainGrid.Children.Add(btb);
                        
                        HelperClasses.HelperFunctions.SlideIn(btb,text.Length*-15, 0, TimeSpan.FromSeconds(0.2));
                    }
                )
            );
        }
        public void SetClickableNotification(string text, Color fontColor, Color backgroundColor, string id, object tag)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        ClearDropDownMessage(id);
                        BackgroundTextBlock btb = new BackgroundTextBlock();
                        btb.ID = id;
                        btb.Effect = new DropShadowEffect();
                        btb.Tag = tag;
                        btb.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
                        btb.VerticalAlignment = VerticalAlignment.Top;
                        btb.FontFamily = new FontFamily("Verdana");
                        btb.BorderRadius = new CornerRadius(0, 0, 20, 0);
                        btb.TextMargin = new Thickness(20, 5, 20, 5);
                        btb.LabelFontSize = 12;
                        btb.Text = text;
                        btb.LabelForeground = new SolidColorBrush(fontColor);
                        btb.BorderBackground = new SolidColorBrush(backgroundColor);
                        btb.Cursor = System.Windows.Input.Cursors.Hand;
                        btb.MouseLeftButtonDown += new MouseButtonEventHandler(OnNotificationClick);
                        _mainGrid.Children.Add(btb);
                        HelperClasses.HelperFunctions.SlideIn(btb, text.Length * -15, 0, TimeSpan.FromSeconds(0.2));
                    }
                )
            );
        }

        void OnNotificationClick(object sender, MouseButtonEventArgs e)
        {
            
            ClearDropDownMessage((sender as BackgroundTextBlock).ID);
            if ((sender as BackgroundTextBlock).Tag is BackgroundTextBlock)
            {
                ((sender as BackgroundTextBlock).Tag as BackgroundTextBlock).BringIntoView();
                ((sender as BackgroundTextBlock).Tag as BackgroundTextBlock).IsSelected = true;
            }
            if((sender as BackgroundTextBlock).Tag is string)
            {
                string command = (sender as BackgroundTextBlock).Tag as string;
                if (command == "_update_")
                {
                    GetLauncherAndDeploy();
                    _updateTimer.Stop();
                }
            }
        }

        private void GetLauncherAndDeploy()
        {
            
        }
        public void SetDropDownMessage(string text, string id)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        SetDropDownMessage(text, Colors.White, Color.FromArgb(128, 115, 115, 115), id);                        
                    }
                )
            );
        }

        public void ClearDropDownMessage(string id)
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        List<BackgroundTextBlock> toRemove = new List<BackgroundTextBlock>();
                        for (int count = 0; count < _mainGrid.Children.Count; count++)
                        {
                            var btb = _mainGrid.Children[count];
                            if (btb is BackgroundTextBlock && (btb as BackgroundTextBlock).ID == id)
                                toRemove.Add( btb as BackgroundTextBlock);
                        }
                        foreach (var item in toRemove)
                        {
                            HelperClasses.HelperFunctions.SlideOutHorizontalAndRemove(item,_mainGrid.Children, item.Text.Length * -15,  TimeSpan.FromSeconds(0.2));
                            
                        }
                        
                    }
                )
            );
        }
        private bool HasActiveNotification()
        {
            for (int count = 0; count < _mainGrid.Children.Count; count ++ )
            {
                if (_mainGrid.Children[count] is BackgroundTextBlock)
                    return true;
            }
            return false;
        }
        private void SetupTrayIcon()
        {
            _notifyIcon = new System.Windows.Forms.NotifyIcon();
            _notifyIcon.Icon = new System.Drawing.Icon(System.Windows.Forms.Application.StartupPath + "\\Images\\app_normal.ico");

            _notifyIcon.Visible = true;

            System.Windows.Forms.MenuItem exitTrayMenu = new System.Windows.Forms.MenuItem("Exit");
          
            HelperClasses.Registry.PopupTrayMenu                = new System.Windows.Forms.MenuItem("Popups");
            HelperClasses.Registry.PopupTrayMenuNewUser         = new System.Windows.Forms.MenuItem("Online User Popup");
            HelperClasses.Registry.PopupTrayMenuLeavingUser     = new System.Windows.Forms.MenuItem("Leaving User Popup");
            HelperClasses.Registry.PopupTrayMenuNewMessage      = new System.Windows.Forms.MenuItem("New Message Popup");

            HelperClasses.Registry.PopupTrayMenu.Click +=new EventHandler(PopupTrayMenu_Click);       
            HelperClasses.Registry.PopupTrayMenuNewUser.Click   +=new EventHandler(PopupTrayMenu_Click); 
            HelperClasses.Registry.PopupTrayMenuLeavingUser.Click+=new EventHandler(PopupTrayMenu_Click);
            HelperClasses.Registry.PopupTrayMenuNewMessage.Click += new EventHandler(PopupTrayMenu_Click);

            

           exitTrayMenu.Click +=new EventHandler(exitTrayMenu_Click);

            _notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu();

            HelperClasses.Registry.PopupTrayMenu.MenuItems.Add(HelperClasses.Registry.PopupTrayMenuNewUser);
            HelperClasses.Registry.PopupTrayMenu.MenuItems.Add(HelperClasses.Registry.PopupTrayMenuLeavingUser);
            HelperClasses.Registry.PopupTrayMenu.MenuItems.Add(HelperClasses.Registry.PopupTrayMenuNewMessage);
            _notifyIcon.ContextMenu.MenuItems.Add(HelperClasses.Registry.PopupTrayMenu);
            _notifyIcon.ContextMenu.MenuItems.Add("-");
            _notifyIcon.ContextMenu.MenuItems.Add(exitTrayMenu);

            _notifyIcon.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(_notifyIcon_MouseDoubleClick);
            _notifyIcon.Text = "WGM Beta3";
            SetPopupMenu();
        }

        void PopupTrayMenu_Click(object sender, EventArgs e)
        {
            if (sender is System.Windows.Forms.MenuItem)
            {
                System.Windows.Forms.MenuItem item = sender as System.Windows.Forms.MenuItem;
                if (item != HelperClasses.Registry.PopupTrayMenu)
                {
                    item.Checked = !item.Checked;

                    HelperClasses.Registry.Settings.ShowNewMessagePopup    =  HelperClasses.Registry.PopupTrayMenuNewMessage.Checked  ;
                    HelperClasses.Registry.Settings.ShowOfflinePopup       =         HelperClasses.Registry.PopupTrayMenuLeavingUser.Checked ;
                    HelperClasses.Registry.Settings.ShowOnlinePopup        =      HelperClasses.Registry.PopupTrayMenuNewUser.Checked     ;


                    HelperClasses.Registry.NotifyListeners(new LocalMessage() { MessageType = LocalMessageTypes.SYSTEM_OPTIONS_CHANGED });
                }

                

            }
        }

        private void SetPopupMenu()
        {
            HelperClasses.Registry.PopupTrayMenuNewMessage.Checked  =HelperClasses.Registry.Settings.ShowNewMessagePopup;
            HelperClasses.Registry.PopupTrayMenuLeavingUser.Checked =HelperClasses.Registry.Settings.ShowOfflinePopup ;
            HelperClasses.Registry.PopupTrayMenuNewUser.Checked = HelperClasses.Registry.Settings.ShowOnlinePopup;   

        }

        void _notifyIcon_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            ShowMainWindow();
        }



        void exitTrayMenu_Click(object sender, EventArgs e)
        {
            WGMMessage leavingMsg = new WGMMessage();
            leavingMsg.SenderLogon = HelperClasses.Registry.Username;
            leavingMsg.MessageType = MessageTypes.USER_LEAVING;
            HelperClasses.Registry.Engine.SendMessageToServer(leavingMsg);
            Thread.Sleep(300);
            ShutdownApplication();
        }
        public void FlashWindow()
        {
            FlashWindow(new WindowInteropHelper(this).Handle);
        }
        /// <summary>
        /// Used to flash a window's taskbar holder.
        /// </summary>
        /// <param name="handle">The window handler of the window to flash.</param>
        private void FlashWindow(IntPtr handle)
        {
            //int FLASHW_STOP = 0;
            //int FLASHW_CAPTION = 1;
            //int FLASHW_TRAY = 2;
            int FLASHW_ALL = 3;
            //int FLASHW_TIMER = 4;
            int FLASHW_TIMERNOFG = 12;
            FLASHWINFO pwfi = new FLASHWINFO();
            pwfi.cbSize = Marshal.SizeOf(pwfi);
            pwfi.hwnd = handle;
            pwfi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG;
            pwfi.uCount = 3;
            pwfi.dwTimeout = 0;
            Int32 intRet = FlashWindowEx(ref pwfi);
        }
        #endregion


        /// <summary>
        /// Used to shutdown the current application.
        /// </summary>
        public void ShutdownApplication()
        {
            this.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        CleanupTemp();
                        HelperClasses.Registry.Settings.LastWindowHeight = Math.Max( this.ActualHeight, 600);
                        HelperClasses.Registry.Settings.LastWindowWidth = Math.Max(this.ActualWidth, 800);
                        HelperClasses.Registry.Settings.LastWindowX = Math.Max(10, this.Left);
                        HelperClasses.Registry.Settings.LastWindowY = Math.Max(10, this.Top);
                        HelperClasses.HelperFunctions.SaveSettings();
                        Process ps = Process.GetCurrentProcess();

                        if (_notifyIcon != null)
                            _notifyIcon.Dispose();
                        ps.Kill();

                        ps.Close();
                    }
                )
            );
        }

        private static void CleanupTemp()
        {
            try
            {

                string baseDir = (HelperClasses.Registry.WorkingDir + "Temp");
                if (!Directory.Exists(baseDir))
                    Directory.CreateDirectory(baseDir);
                DirectoryInfo di = new DirectoryInfo(baseDir);
                var files = di.GetFiles();
                foreach (var file in files)
                {
                    try
                    {
                        file.Delete();
                    }
                    catch { }
                }
            }
            catch (Exception ex)
            {
                HelperClasses.HelperFunctions.LogException(ex);
            }
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {

            CleanupTemp();
            HelperClasses.HelperFunctions.SlideIn(_wgmBgImg, 0, _wgmBgImg.ActualHeight, TimeSpan.FromSeconds(0.2));
            
        }

        private void OnInnerTabSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                foreach (TabItem item in e.AddedItems)
                {
                    (item.Tag as BackgroundTextBlock).IsSelected = true;
                }
                foreach (TabItem item in e.RemovedItems)
                {
                    (item.Tag as BackgroundTextBlock).IsSelected = false;
                }
            }
            catch { }
        }

        private void OnConversationSelected(object sender, MouseButtonEventArgs e)
        {
            if (!_conversationSelector.IsSelected)
            {
                _conversationSelector.IsSelected = true;
                //HelperClasses.HelperFunctions.SlideOut(_innerTabControl, this.ActualHeight, 0, TimeSpan.FromSeconds(0.2));

                HelperClasses.HelperFunctions.SlideIn(_innerTabControl, this.ActualWidth * -1, 0, TimeSpan.FromSeconds(0.2));
            }
        }

        private void OnProfileSelected(object sender, MouseButtonEventArgs e)
        {
            if (!_profileSelector.IsSelected)
            {
                _profileSelector.IsSelected = true;
                //HelperClasses.HelperFunctions.SlideOut(_innerTabControl, this.ActualHeight, 0, TimeSpan.FromSeconds(0.2));

                HelperClasses.HelperFunctions.SlideIn(_innerTabControl, this.ActualWidth * -1, 0, TimeSpan.FromSeconds(0.2));
                _profileView.ResetAll();
            }
        }

        private void OnHistorySelected(object sender, MouseButtonEventArgs e)
        {
            _historySelector.IsSelected = true;
            //HelperClasses.HelperFunctions.SlideOut(_innerTabControl, this.ActualHeight, 0, TimeSpan.FromSeconds(0.2));

            HelperClasses.HelperFunctions.SlideIn(_innerTabControl, this.ActualWidth * -1, 0, TimeSpan.FromSeconds(0.2));
            
        }

        private void OnSettingsSelected(object sender, MouseButtonEventArgs e)
        {
            if (!_settingsSelector.IsSelected)
            {
                _settingsSelector.IsSelected = true;

                _settingsView.RestoreOptions();
                HelperClasses.HelperFunctions.SlideIn(_innerTabControl, this.ActualWidth * -1, 0, TimeSpan.FromSeconds(0.2));
            }
        }

        private void OnChatSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                foreach (TabItem item in e.AddedItems)
                {
                    (item.Tag as BackgroundTextBlock).IsSelected = true;
                }
                foreach (TabItem item in e.RemovedItems)
                {
                    (item.Tag as BackgroundTextBlock).IsSelected = false;
                }
            }
            catch { }
        }

        private void OnSizeChanged(object sender, SizeChangedEventArgs e)
        {
//more
//TODO

        }




    }
}
